#pragma once
#include <functional>
#include <signal.h>
#include "tcp_socket.hpp"
typedef std::function<void (const std::string& req, std::string* resp)> Handler;
 多进程版本的 Tcp 服务器
 class TcpProcessServer {
 public:
 TcpProcessServer(const std::string& ip, uint16_t port) : ip_(ip), port_(port) {
 // 需要处理子进程
 signal(SIGCHLD, SIG_IGN);
 }
 void ProcessConnect(const TcpSocket& new_sock, const std::string& ip, uint16_t port,
Handler handler) {
int ret = fork();
if (ret > 0) {
 father
 // 父进程不需要做额外的操作, 直接返回即可.
 // 思考, 这里能否使用 wait 进行进程等待?
 // 如果使用 wait , 会导致父进程不能快速再次调用到 accept, 仍然没法处理多个请求
 // [注意!!] 父进程需要关闭 new_sock
new_sock.Close();
return;
} else if (ret == 0) {
// child
for (;;) {
std::string req;
bool ret = new_sock.Recv(&req);
if (!ret) { // 处理具体的连接过程. 每个连接一个子进程
// 当前的请求处理完了, 可以退出子进程了. 注意, socket 的关闭在析构函数中就完成了
printf("[client %s:%d] disconnected!\n", ip.c_str(), port);
exit(0);
}
std::string resp;
handler(req, &resp);
new_sock.Send(resp);
printf("[client %s:%d] req: %s, resp: %s\n", ip.c_str(), port,
req.c_str(), resp.c_str());
}
} else {
perror("fork");
}
}
bool Start(Handler handler) {
// 1. 创建 socket;
 CHECK_RET(listen_sock_.Socket());
 // 2. 绑定端口号
 CHECK_RET(listen_sock_.Bind(ip_, port_));
 // 3. 进行监听
 CHECK_RET(listen_sock_.Listen(5));
 // 4. 进入事件循环
 for (;;) {
 // 5. 进行 accept
 TcpSocket new_sock;
std::string ip;
uint16_t port = 0;
if (!listen_sock_.Accept(&new_sock, &ip, &port)) {
continue;
}
printf("[client %s:%d] connect!\n", ip.c_str(), port);
ProcessConnect(new_sock, ip, port, handler);
}
return true;
}
private:
TcpSocket listen_sock_;
std::string ip_;
uint64_t port_;
};
